package com.atguigu.gmall.ums.service.impl;



import com.atguigu.gmall.common.consts.Keys;
import com.atguigu.gmall.common.exception.AuthException;

import com.atguigu.gmall.common.utils.HttpUtils;
import com.atguigu.gmall.ums.config.RedisTemplateConfig;
import com.atguigu.gmall.ums.config.UmsProperties;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;


import com.google.gson.Gson;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;

import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import java.util.*;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.gmall.common.bean.PageResultVo;
import com.atguigu.gmall.common.bean.PageParamVo;

import com.atguigu.gmall.ums.mapper.UserMapper;
import com.atguigu.gmall.ums.entity.UserEntity;
import com.atguigu.gmall.ums.service.UserService;
import org.springframework.util.CollectionUtils;


@Service("userService")
//@EnableConfigurationProperties(UmsProperties.class)
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisTemplateConfig redisTemplate;
    @Autowired
    private UmsProperties properties;

    @Override
    public PageResultVo queryPage(PageParamVo paramVo) {
        IPage<UserEntity> page = this.page(
                paramVo.getPage(),
                new QueryWrapper<UserEntity>()
        );

        return new PageResultVo(page);
    }

    @Override
    public Boolean checkDataByType(String data, Integer type) {
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        switch(type){
            case 1:
                wrapper.eq(UserEntity::getUsername,data);
                break;
            case 2:
                wrapper.eq(UserEntity::getPhone,data);
                break;
            case 3:
                wrapper.eq(UserEntity::getEmail,data);
                break;
            default:
                return null;
        }
        return this.userMapper.selectCount(wrapper) == 0;
    }

    @Override
    public String getCodeByPhone(String phone) {


        return null;
    }

    @Override
    public void register(UserEntity userEntity, String code) {
        // TODO: 1.校验验证码: 根据手机号查询redis中的code 和 页面的code 比较
        // 2.生成盐
        String salt = StringUtils.substring(UUID.randomUUID().toString(), 0, 6);
        userEntity.setSalt(salt); //这个盐后续查询时,依然会使用该盐对用户输入明文密码 进行加盐加密
        // 3.加盐加密 然后使用密文密码把明文密码覆盖
        String password = DigestUtils.md5Hex(userEntity.getPassword() + salt);
        userEntity.setPassword(password);
        //4.新增用户
        userEntity.setLevelId(1l);
        userEntity.setNickname(userEntity.getUsername());
        userEntity.setSourceType(1);
        userEntity.setIntegration(1000);
        userEntity.setGrowth(1000);
        userEntity.setStatus(1);
        userEntity.setCreateTime(new Date());
        this.save(userEntity);
        // TODO: 5.删除redis中的验证码
    }

    @Override
    public UserEntity queryUser(String loginName, String password) {
        // 根据登录名查询,查询出复合登录名的用户
        LambdaQueryWrapper<UserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserEntity::getUsername,loginName).or().eq(UserEntity::getPhone,loginName).or().eq(UserEntity::getEmail,loginName);
        List<UserEntity> userEntities = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(userEntities)){
            return null; // 用户输入不合法
        }

        //遍历用户集合,获取每个用户的盐,然后对用户输入的明文密码passworld加盐加密
        for (UserEntity userEntity : userEntities) {
            String pwd = DigestUtils.md5Hex(password + userEntity.getSalt());
            if (StringUtils.equals(pwd,userEntity.getPassword())){
                return userEntity;
            }
        }
        // 密码输入的不合法,直接返回null
        return null;
    }

    @Override
    public void send(String mobile, String checkCode) {
        //1.验证手机号码发送短信的频率
        String mobileCodePerMinKey = Keys.CODE_PER_MIN_KEY + mobile;
        if (redisTemplate.redisTemplateInit().hasKey(mobileCodePerMinKey)){
            throw new AuthException("短信发送过于频繁");
        }
        String mobileCodePerDayKey = Keys.CODE_PER_DAY_KEY + mobile;
        Object count = redisTemplate.redisTemplateInit().opsForValue().get(mobileCodePerDayKey);
        if (count != null){
            if (Integer.parseInt(count.toString()) >= 5){
                throw new AuthException("当天短信发送次数达到上限");
            }
        }else {
            //如果code为空,代表该手机号第一次来获取验证码
            redisTemplate.redisTemplateInit().opsForValue().set(mobileCodePerDayKey,0,24, TimeUnit.HOURS);
        }
        String host = properties.getHost();
        String path = properties.getPath();
        String method = properties.getMethod();
        String appcode = properties.getAppcode();
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        Map<String, String> querys = new HashMap<String, String>();
        querys.put("mobile", mobile);
        querys.put("param", "code:" + checkCode);
        querys.put("tpl_id", "TP1711063");
        Map<String, String> bodys = new HashMap<String, String>();
        try {

            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            //System.out.println(response.toString() );
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            System.out.println("result = " + result);
            //获取response的body
            //System.out.println(EntityUtils.toString(response.getEntity()));
            //判断短信发送成功还是失败
            Gson gson= new Gson();
            Map map = gson.fromJson(result, Map.class);

            String resultCode = map.get("return_code").toString();

            if (!"00000".equals(resultCode)){
                throw new AuthException("短信发送失败");
            }
            //6.更新用户获取验证码的频率
            redisTemplate.redisTemplateInit().opsForValue().set(mobileCodePerMinKey,mobileCodePerMinKey,1,TimeUnit.MINUTES);
            //更新手机号码今天获取验证码的次数
            //incr key; 如果key不存在,默认值为0; 加完之后变为1,如果key存在且是数字，自增1
            redisTemplate.redisTemplateInit().opsForValue().increment(mobileCodePerDayKey);


        } catch (Exception e) {
            //log.error(ExceptionUtils.getStackTrace(e));
            throw new AuthException("短信发送失败");
        }
    }
}




















